/*
 * @Author: xiguan
 * @Email: xiguan.teng@qq.com
 * @Version: 1.0
 * @Date: 2022-07-29 14:28:47
 * @LastEditTime: 2022-07-31 11:32:21
 */

#ifndef _REVERSEITERATORMy_H_
#define _REVERSEITERATORMy_H_

#include "IteratorMy.h"

namespace MySTL{


    template<class Iterator>
    class reverse_iterator_t{

    public:
        typedef Iterator                                                iterator_type;
        typedef typename iterator_traits<Iterator>::iterator_category    iterator_category;
        typedef typename iterator_traits<Iterator>::value_type           value_type;
        typedef typename iterator_traits<Iterator>::difference_type      difference_type;
        typedef typename iterator_traits<Iterator>::pointer              pointer;
        typedef const pointer                                           const_pointer;
        typedef typename iterator_traits<Iterator>::reference            reference;
        typedef const reference                                         const_reference;

    private:
        Iterator base_;
        Iterator cur_;

    public:
        // 构造函数 析构函数 等
        reverse_iterator_t() : base_(0), cur_(0){}
        explicit reverse_iterator_t( const iterator_type &it ) : base_(it){
            auto temp = it;
            cur_ = --temp;
        }
        template<class Iter>
        reverse_iterator_t( const reverse_iterator_t<Iter> &rev_it ){
            base_ = (iterator_type)rev_it.base_;
            auto temp = base_;
            cur_ = --temp;
        }

    public:
        // 其他成员函数
        iterator_type getBase(){
            return base_;
        }
        reference operator*(){
            return (*cur_);
        }
        const_reference operator*() const {
            return (*cur_);
        }
        pointer operator->(){
            return &(operator*());
        }
        const_pointer operator->() const {
            return &(operator*());
        }
        reverse_iterator_t &operator++(){
            --base_;
            --cur_;
            return *this;
        }
        reverse_iterator_t &operator++(int){
            reverse_iterator_t temp = *this;
            ++(*this);
            return temp;
        }
        reverse_iterator_t &operator--(){
            ++base_;
            ++cur_;
            return *this;
        }
        reverse_iterator_t &operator--(int){
            reverse_iterator_t temp = *this;
            --(*this);
            return temp;
        }
        reference operator[]( difference_type n ){
            return getBase()[-n-1];
        }
        reverse_iterator_t operator+( difference_type n ) const;
		reverse_iterator_t &operator+=( difference_type n );
		reverse_iterator_t operator-( difference_type n ) const;
		reverse_iterator_t &operator-=( difference_type n );

    private:
        Iterator _advanceNStep( Iterator it, difference_type n, bool right, // true ->, false -<
            random_access_iterator_tag )
        {
            if( right ){
                it += n;
            }else{
                it -= n;
            }
            return it;
        }

        Iterator _advanceNStep( Iterator it, difference_type n, bool right, // true ->, false -<
            bidirectional_iterator_tag )
        {
            difference_type i;
            difference_type absN = n >= 0 ? n : -n;
            // ->
            if( (right && n > 0) || (!right && n < 0 ) ){
                for( i = 0; i != absN; ++ i ){
                    it = it + 1;
                }   
            }else if( (!right && n > 0) || (right && n < 0) ){
                for( i = 0; i != absN; ++ i ){
                    it = it - 1;
                }
            }
            return it;
        }

    public:
        template<class Iteratorf>
        friend bool operator==( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );
        template<class Iteratorf>
        friend bool operator!=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );
        template<class Iteratorf>
        friend bool operator<( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );
        template<class Iteratorf>
        friend bool operator>( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );
        template<class Iteratorf>
        friend bool operator<=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );
        template<class Iteratorf>
        friend bool operator>=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs );

        template<class Iteratorf>
        friend reverse_iterator_t<Iteratorf> operator+( 
            typename reverse_iterator_t<Iteratorf>::difference_type n, 
            const reverse_iterator_t<Iteratorf> &rev_it );
        template<class Iteratorf>
        friend typename reverse_iterator_t<Iteratorf>::difference_type operator-( 
            const reverse_iterator_t<Iteratorf> &lhs, 
            const reverse_iterator_t<Iteratorf> &rhs );

    };


    template<class Iterator>
    reverse_iterator_t<Iterator> &reverse_iterator_t<Iterator>::operator+=( difference_type n ){
        base_ = _advanceNStep( base_, n, false, iterator_category() );
        cur_ = _advanceNStep( cur_, n, false, iterator_category() );
        return *this;
    }
    template<class Iterator>
    reverse_iterator_t<Iterator> &reverse_iterator_t<Iterator>::operator-=( difference_type n ){
        base_ = _advanceNStep( base_, n, true, iterator_category() );
        cur_ = _advanceNStep( cur_, n, true, iterator_category() );
        return *this;
    }
    template<class Iterator>
    reverse_iterator_t<Iterator> reverse_iterator_t<Iterator>::operator+( difference_type n ) const {
        reverse_iterator_t<Iterator> res = *this;
        res += n;
        return res;
    }
    template<class Iterator>
    reverse_iterator_t<Iterator> reverse_iterator_t<Iterator>::operator-( difference_type n ) const {
        reverse_iterator_t<Iterator> res = *this;
        res -= n;
        return res;
    }

    template <class Iteratorf>
	bool operator==( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return lhs.cur_ == rhs.cur_;
	}
	template <class Iteratorf>
	bool operator!=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return !(lhs == rhs);
	}
	template <class Iteratorf>
	bool operator<( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return lhs.cur_ < rhs.cur_;
	}
	template <class Iteratorf>
	bool operator>( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return lhs.cur_ > rhs.cur_;
	}
	template <class Iteratorf>
	bool operator>=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return !(lhs < rhs);
	}
	template <class Iteratorf>
	bool operator<=( const reverse_iterator_t<Iteratorf> &lhs, const reverse_iterator_t<Iteratorf> &rhs ){
		return !(lhs > rhs);
	}

    template<class Iteratorf>
    reverse_iterator_t<Iteratorf> operator+( 
        typename reverse_iterator_t<Iteratorf>::difference_type n, 
        const reverse_iterator_t<Iteratorf> &rev_it )
    {
        return rev_it + n;
    }
        
    template<class Iteratorf>
    typename reverse_iterator_t<Iteratorf>::difference_type operator-( 
        const reverse_iterator_t<Iteratorf> &lhs, 
        const reverse_iterator_t<Iteratorf> &rhs )
    {
        return lhs.cur_ - rhs.cur_;
    }

}


#endif